package com.yjzx.care;

import com.yjzx.care.base.BaseElement;
import com.yjzx.care.base.Element;

import java.util.function.BooleanSupplier;

/**
 * @author yjzx
 * @date 2023/12/25
 * @description 无返回值的判断
 */
public final class ElementNoReturn extends BaseElement {
    public interface NoReturnElse extends Else {
        /**
         * 最后的else
         *
         * @param runnable 运行方法
         */
        void otherwise(Runnable runnable);

        /**
         * if else
         *
         * @param whether  判断
         * @param runnable 运行方法
         * @return 返回else接口
         */
        ElementNoReturn.NoReturnElse otherwise(boolean whether, Runnable runnable);

        ElementNoReturn.NoReturnElse otherwise(BooleanSupplier whether, Runnable runnable);
    }

    private final ElementNoReturn.NoReturnElse defaultElse = new ElementNoReturn.NoReturnElse() {
        @Override
        public void otherwise(Runnable runnable) {
            ifExist(true, runnable);
        }

        @Override
        public ElementNoReturn.NoReturnElse otherwise(boolean whether, Runnable runnable) {
            return ifExist(whether, runnable);
        }

        @Override
        public NoReturnElse otherwise(BooleanSupplier whether, Runnable runnable) {
            return ifExist(isWhether() && whether.getAsBoolean(), runnable);
        }
    };
    private final ElementNoReturn.NoReturnElse noopElse = new ElementNoReturn.NoReturnElse() {
        @Override
        public void otherwise(Runnable consumer) {
        }

        @Override
        public ElementNoReturn.NoReturnElse otherwise(boolean whether, Runnable consumer) {
            return noopElse;
        }

        @Override
        public NoReturnElse otherwise(BooleanSupplier whether, Runnable runnable) {
            return noopElse;
        }
    };

    ElementNoReturn() {
    }

    public ElementNoReturn.NoReturnElse ifExist(boolean whether, Runnable runnable) {
        if (whether && exist(true)) {
            runnable.run();
            return noopElse;
        }
        return isWhether() ? this.defaultElse : this.noopElse;
    }

    public final static class ElementNoReturnBuilder implements MyInterface {
        ElementNoReturnBuilder() {
        }

        public NoReturnElseBuilder ifExistToBuilder(boolean whether, Runnable runnable) {
            return new NoReturnElseBuilder(whether ? runnable : null);
        }

        @SafeVarargs
        public final NoReturnElseBuilder noReturnBuilder(Element<Runnable>... elements) {
            Runnable value = null;
            for (Element<Runnable> element : elements) {
                if ((value = element.getValue()) != null) {
                    break;
                }
            }
            return new NoReturnElseBuilder(value);
        }

        public static class NoReturnElseBuilder {
            private volatile Runnable runnable;
            private volatile boolean flag = true;

            public NoReturnElseBuilder(Runnable runnable) {
                this.runnable = runnable;
            }

            public synchronized NoReturnElseBuilder otherwise(boolean whether, Runnable runnable) {
                if (this.runnable != null && whether) {
                    this.runnable = runnable;
                }
                return this;
            }

            public synchronized NoReturnElseBuilder otherwise(BooleanSupplier whether, Runnable runnable) {
                if (this.runnable != null && whether.getAsBoolean()) {
                    this.runnable = runnable;
                }
                return this;
            }

            public synchronized NoReturnElseBuilder otherwise(Runnable runnable) {
                if (this.runnable != null) {
                    this.runnable = runnable;
                }
                return this;
            }

            public synchronized void otherwiseBuild(Runnable runnable) {
                if (this.runnable != null) {
                    this.runnable = runnable;
                }
                build();
            }

            public synchronized void build() {
                if (flag) {
                    flag = false;
                    runnable.run();
                    runnable = null;
                    flag = true;
                } else {
                    throw new IllegalStateException("Exist or Builder can only be used once.");
                }
            }
        }

    }

}
